import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
// import ReportFormOrderCostAnalyse from '@main/entities/service/admin/reportForm/report-form-period-status-monitoring.entity';
import { Repository, Between, Like, In } from 'typeorm';
import BaseMachine from '@main/entities/service/admin/base/base-machine.entity';
import WipOrderReport from '@main/entities/service/admin/wip/wip-order-report.entity';
import ProductionOrder from '@main/entities/service/admin/production/production-order.entity';
import { ApiException } from '@main/common/exceptions/api.exception';
import { generateExcelFn } from '@main/excel';
import { format } from 'date-fns';

@Injectable()
export class ReportFormOrderCostAnalyseService {
  constructor(
    @InjectRepository(BaseMachine)
    private machineRepository: Repository<BaseMachine>,
    // @InjectRepository(ReportFormOrderCostAnalyse)
    // private reportFormOrderCostAnalyseRepository: Repository<ReportFormOrderCostAnalyse>,
    @InjectRepository(WipOrderReport)
    private orderReportRepository: Repository<WipOrderReport>,
    @InjectRepository(ProductionOrder)
    private orderRepository: Repository<ProductionOrder>
  ) {}

  /**
   * 罗列所有配置
   */
  async page(data) {
    const { pageSize, pageNum, entity = {} } = data;

    const { actualCompleteTime, fastSearch, machineList, ids = [] } = entity;

    const where: any[] = []; // 初始化为数组以便后续拼接

    // 处理 userIdList 进行匹配
    if (actualCompleteTime && actualCompleteTime.length) {
      if (machineList && machineList.length) {
        if (fastSearch) {
          where.push(
            {
              orderStatusCode: '40',
              machineCode: In(machineList),
              materialCode: Like(`%${fastSearch}%`),
              actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
            },
            {
              orderStatusCode: '40',
              machineCode: In(machineList),
              materialName: Like(`%${fastSearch}%`),
              actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
            },
            {
              orderStatusCode: '40',
              machineCode: In(machineList),
              orderCode: Like(`%${fastSearch}%`),
              actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
            },
            {
              orderStatusCode: '40',
              machineCode: In(machineList),
              customCode: Like(`%${fastSearch}%`),
              actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
            },
            {
              orderStatusCode: '40',
              machineCode: In(machineList),
              customShort: Like(`%${fastSearch}%`),
              actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
            },
            {
              orderStatusCode: '40',
              machineCode: In(machineList),
              customName: Like(`%${fastSearch}%`),
              actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
            }
          );
        } else {
          where.push({
            orderStatusCode: '40',
            machineCode: In(machineList),
            actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
          });
        }
      } else if (fastSearch) {
        where.push(
          {
            orderStatusCode: '40',
            materialCode: Like(`%${fastSearch}%`),
            actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
          },
          {
            orderStatusCode: '40',
            materialName: Like(`%${fastSearch}%`),
            actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
          },
          {
            orderStatusCode: '40',
            orderCode: Like(`%${fastSearch}%`),
            actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
          },
          {
            orderStatusCode: '40',
            customCode: Like(`%${fastSearch}%`),
            actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
          },
          {
            orderStatusCode: '40',
            customShort: Like(`%${fastSearch}%`),
            actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
          },
          {
            orderStatusCode: '40',
            customName: Like(`%${fastSearch}%`),
            actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
          }
        );
      } else {
        where.push({
          orderStatusCode: '40',
          actualCompleteDate: Between(actualCompleteTime[0], actualCompleteTime[1]),
        });
      }
    }

    if (ids && ids.length) {
      for (const item of where) {
        item['id'] = In(ids);
      }
    }

    const [orderList, total]: any = await this.orderRepository.findAndCount({
      where,
      order: {
        updateTime: 'DESC',
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize,
    });

    // const electricityPrice =
    //   (await this.paramConfigService.findValueByCode('electricityPrice')) || 0;

    // const waterPrice = (await this.paramConfigService.findValueByCode('waterPrice')) || 0;

    await Promise.all(
      orderList.map(async (item) => {
        const { orderCode, machineCode, actualCompleteDate } = item;

        const orderReportList = await this.orderReportRepository.find({
          where: {
            orderCode,
            machineCode,
            reportFinishStatus: 1,
          },
          order: { updateTime: 'DESC' },
        });

        let productTime: any = 0;

        let allElectricityConsumption = 0; // 总用电量

        let allWaterConsumption = 0; // 总用水量

        let allElectricityBill = 0; // 电费

        let allWaterBill = 0; //水费

        let allInkUsage = 0; // 水墨总用量

        let allLaborCost = 0; // 人工费

        let allGoodNum = 0; //良品数

        let allMaterialCost = 0; // 材料成本

        let allVariableManufactureCost = 0; // 变动制造成本

        if (orderReportList && orderReportList.length) {
          for (const mItem of orderReportList) {
            const {
              reportTime,
              createTime,
              electricityConsumption,
              waterBill,
              electricityBill,
              waterConsumption,
              inkUsage,
              laborCost,
              materialCost,
              variableManufactureCost,
              goodNum,
            } = mItem;

            if (createTime && reportTime) {
              productTime += new Date(reportTime).getTime() - new Date(createTime).getTime();
            }

            if (electricityConsumption) {
              allElectricityConsumption += electricityConsumption;
            }

            if (waterConsumption) {
              allWaterConsumption += waterConsumption;
            }

            if (electricityBill) {
              allElectricityBill += electricityBill;
            }

            if (waterBill) {
              allWaterBill += waterBill;
            }

            if (inkUsage) {
              allInkUsage += inkUsage;
            }

            if (laborCost) {
              allLaborCost += laborCost;
            }

            if (materialCost) {
              allMaterialCost += materialCost;
            }

            if (variableManufactureCost) {
              allVariableManufactureCost += variableManufactureCost;
            }

            if (goodNum) {
              allGoodNum += goodNum;
            }
          }
        }

        const obj = await this.machineRepository.findOne({ where: { machineCode } });

        item.machineName = obj.machineName || '-';

        item.allElectricityConsumption = allElectricityConsumption;

        item.allWaterConsumption = allWaterConsumption;

        item.electricityBill = allElectricityBill;

        item.waterBill = allWaterBill;

        item.allInkUsage = allInkUsage;

        item.allLaborCost = allLaborCost;

        item.goodNum = allGoodNum;

        item.allMaterialCost = allMaterialCost;

        item.allVariableManufactureCost = allVariableManufactureCost.toFixed(2);

        item.productTime = (productTime / 1000 / 60).toFixed(2);

        if (actualCompleteDate) {
          item.actualCompleteTime = format(new Date(actualCompleteDate), 'yyyy-MM-dd HH:mm:ss');
        }
      })
    );

    return [orderList, total];
  }

  async export(dto, lang) {
    const [list] = await this.page(dto);

    if (!list || !(list as any).length) {
      throw new ApiException(10052);
    }

    const dataList = list;

    return await generateExcelFn(
      {
        sheetName: 'productionStatistics',
        mainHeaderList: [
          {
            label: 'orderCode',
          },
          {
            label: 'machineName',
          },
          {
            label: 'materialCode',
          },
          {
            label: 'materialName',
          },
          {
            label: 'version',
          },
          {
            label: 'customName',
          },
          {
            label: 'orderNum',
          },
          {
            label: 'paperboardNum',
          },
          {
            label: 'goodNum',
          },
          {
            label: 'paperPrice',
          },
          {
            label: 'materialPrice',
          },
          {
            label: 'productTime',
          },
          {
            label: 'electricityConsumption',
            prop: 'allElectricityConsumption',
          },
          {
            label: 'waterConsumption',
            prop: 'allWaterConsumption',
          },
          {
            label: 'electricityBill',
          },
          {
            label: 'waterBill',
          },
          {
            label: 'laborCost',
            prop: 'allLaborCost',
          },
          {
            label: 'materialCost',
            prop: 'allMaterialCost',
          },
          {
            label: 'variableManufactureCost',
            prop: 'allVariableManufactureCost',
          },
          {
            label: 'actualCompleteTime',
          },
        ],
        dataList,
      },
      lang
    );
  }
}
